#include "atom.h"
#include "ram.h"
#include "kassert.h"
#include "debug.h"
#include "console.h"
#include "syslog.h"
#include <string.h>

void*   RamAlloc(Ram* dev, size_t size)
{
    kassert(dev->Protected.alloc != NULL);
    return dev->Protected.alloc(dev, size);
}

void    RamFree(Ram* dev, void *mem)
{
    kassert(dev->Protected.free != NULL);
    dev->Protected.free(dev, mem);
}

void*   RamRealloc(Ram* dev, void *mem, size_t size)
{
    kassert(dev->Protected.realloc != NULL);
    return dev->Protected.realloc(dev, mem, size);
}

void    RamUseage(Ram* dev, RamInfo *info)
{
    kassert(dev->Protected.useage != NULL);
    dev->Protected.useage(dev, info);
}

static enConsoleResult ram_cmd(int argc, char** argv)
{
    enConsoleResult ret = CE_OK;

	if (argc >= 3) {
        FD ramfd = open(argv[1], 0, 0);
        Ram* dev = (Ram*)ramfd;
        if (dev != NULL) {
            RamInfo info;
            RamUseage(dev, &info);

            if( strcmp(argv[2], "usage") == 0) {
                KPrintf("mem :%s \r\n", dev->super.name);
                KPrintf("\t total: %d\r\n", info.total_bytes);
                KPrintf("\t free : %d\r\n", info.free_bytes);
            }else if( strcmp(argv[2], "test") == 0 ){
                size_t testsize = 1024 * 1024;
                uint8_t *data = (uint8_t*)RamAlloc(dev, testsize);
                KPrintf("alloc at : %08X\r\n", (uint32_t)data);
                testsize += 1024 * 1024;
                data = (uint8_t*)RamRealloc(dev, data, testsize);
                KPrintf("realloc at : %08X\r\n", (uint32_t)data);
                
                for( int i=0; i < testsize; i++){
                    data[i] = 0x55;
                }
                KPrint("write test success!\r\n");
                for( int i=0; i < testsize; i++){
                    if( data[i] != 0x55){
                        ret = CE_RUNTIME_ERROR;
                        break;
                    }
                }
                RamFree(dev, data);
                KPrintf("read test %s!\r\n", (ret == CE_RUNTIME_ERROR ? "failure" : "success"));
            }
        }
        else {
            SYSLOG(LOG_ERR, "no device found!");
        }
        close(ramfd);
	}
	else {
		KPrint("ram [name] usage - print memory useage\r\n");
        KPrint("ram [name] test  - test memory\r\n");
	}

	return ret;
}

BGEIN_DEF_CMD(_cmd)
	CMD_DEF_ALISA(ram, ram_cmd, "ram [name] - print memory useage")
END_DEF_CMD(_pwmCmd)


void  RamCreate(Ram *dev, const char *name)
{
    IosDrvInstall(&dev->super, name);

#if defined(BSP_USE_RAM) && defined(COM_USE_RAM_CMD)    
    CONSOLE_REG_CMD(_cmd);
#endif 
}
